package com.grace.oss.service.impl;

import java.awt.image.BufferedImage;
import java.io.FileInputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

import javax.imageio.ImageIO;

import com.grace.common.enums.GraceServerRoot;
import com.grace.common.enums.GraceStorageRoot;
import com.grace.common.exception.file.FileSizeLimitExceededException;
import com.grace.common.exception.file.InvalidExtensionException;
import com.grace.common.utils.file.FileUploadUtils;
import com.grace.oss.domain.OlyOss;
import com.grace.oss.enums.OssEnum;
import com.grace.oss.mapper.OssServerMapper;
import com.grace.oss.properties.NativeProperties;
import com.grace.oss.properties.OssConfigProperties;
import com.grace.oss.service.OssHandler;
import com.grace.oss.utils.FileTypes;
import com.grace.oss.utils.OssUtils;
import com.grace.system.service.impl.SysSearchConfigServiceImpl;

import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import net.coobird.thumbnailator.Thumbnails;

/**
 * 储存在本地
 */
@Service
public class NativeOssHandler implements OssHandler {
    /**
     * 缩略图前缀
     */
    public final static String THUMBNAIL_PREFIX = "thumbnail_";

    @Autowired
    private SysSearchConfigServiceImpl configService;

    @Autowired
    private OssServerMapper ossMapper;

    private static final Logger log = LoggerFactory.getLogger(NativeOssHandler.class);

    @Override
    public OlyOss ossUpload(MultipartFile file, GraceStorageRoot serverRoot)
            throws IOException, FileSizeLimitExceededException, InvalidExtensionException {
        OssHandler.check(file, configService);
        // 设置返回结果
        OlyOss data = new OlyOss();
        // 验证支持文件后缀
        // 验证支持类型
        // 二级目录
        String fileType = OssUtils.getFileTypeExtension(FileUploadUtils.getExtension(file));
        // 构造文件key
        String key = OssHandler.getKey(fileType, file, Boolean.parseBoolean(
                configService.selectConfigDefaultValue(OssConfigProperties.OSS_CONFIG_GROUP.defaultValue(),
                        OssConfigProperties.OSS_FILE_NAME_ZH_PY)));
        // 文件上传
        FileUploadUtils.upload(serverRoot.getWorkRoot(key), file);
        data.setFileName(FilenameUtils.getName(file.getOriginalFilename()));
        data.setFileType(fileType);
        data.setSize(file.getSize());
        if (GraceStorageRoot.AVATAR_DIR.getValue().equals(serverRoot.getValue())) {
            data.setFk(OssHandler.pathToUrl(serverRoot.getValue() + "/" + key));
        } else {
            data.setFk(OssHandler.pathToUrl(key));
            if ("image".equals(fileType)) {
                String thumbnailKey = Paths
                        .get(FilenameUtils.getFullPathNoEndSeparator(key),
                                THUMBNAIL_PREFIX + FilenameUtils.getName(key))
                        .toString();
                String thumbnailPath = serverRoot.getWorkRoot(thumbnailKey);
                BufferedImage bufferedImage = ImageIO
                        .read(new FileInputStream(serverRoot.getWorkRoot(key).toString()));
                Thumbnails.of(bufferedImage).size(THUMB_WIDTH, THUMB_HEIGHT).toFile(thumbnailPath.toString());
            }
        }
        data.setOssType(getOssType());
        // 判断是否是图片
        data.setDomain(configService.selectConfigValueByGk(OssConfigProperties.OSS_CONFIG_GROUP.getValue(),
                NativeProperties.OSS_DOMAIN.getValue()));
        ossMapper.insertOlyOss(data);
        return data;
    }

    @Override
    public void ossDelete(String key) {
        Path path = Paths.get(GraceStorageRoot.UPLOAD_DIR.getWorkRoot(key));
        try {
            Files.deleteIfExists(path);
        } catch (IOException e1) {
            log.error(key + "删除失败,原因本地可能不存在", e1);
        }
        if (FileTypes.getImg(FilenameUtils.getExtension(key))) {
            try {
                Files.deleteIfExists(Paths.get(GraceStorageRoot.UPLOAD_DIR.getWorkRoot(),
                        FilenameUtils.getFullPathNoEndSeparator(key), THUMBNAIL_PREFIX + FilenameUtils.getName(key)));
            } catch (IOException e) {
                log.error(key + "附件删除失败,原因本地可能不存在", e);
            }
        }
        ossMapper.deleteOlyOssByFk(OssHandler.pathToUrl(key));
    }

    @Override
    public OlyOss ossAppointUpload(MultipartFile file, GraceServerRoot rootPath, String fileName,
            String[] allowedExtensio) throws IOException, FileSizeLimitExceededException, InvalidExtensionException {
        FileUploadUtils.assertAllowed(file, allowedExtensio);
        // 直接上传 fileName即为key
        if (StringUtils.isNotEmpty(fileName)) {
            FileUploadUtils.upload(rootPath.getWorkRoot(fileName), file);
        } else {
            // 时间路径
            fileName = OssHandler.getKey("", file, true);
            FileUploadUtils.upload(rootPath.getWorkRoot(fileName), file);
        }
        OlyOss olyOss = new OlyOss();
        olyOss.setDomain(configService.selectConfigValueByGk(OssConfigProperties.OSS_CONFIG_GROUP.getValue(),
                NativeProperties.OSS_DOMAIN.getValue()));
        // key 不包含文件夹
        olyOss.setFk(OssHandler.pathToUrl(fileName));
        return olyOss;
    }

    @Override
    public OlyOss ossAppointUpload(MultipartFile file, GraceServerRoot rootPath, String[] allowedExtensio)
            throws IOException, FileSizeLimitExceededException, InvalidExtensionException {
        return ossAppointUpload(file, rootPath, FilenameUtils.getName(file.getOriginalFilename()), allowedExtensio);
    }

    @Override
    public String getOssType() {
        return OssEnum.OSS_TYPE_NATIVE.getValue();
    }

}
